using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodePlex.SpaceBlock;
using CodePlex.Resourceful;

namespace CodePlex.SpaceBlock.UI.Controls.Explore
{
    public partial class FoldersControl : CodePlex.SpaceBlock.UI.Controls.BaseControl, ISupportsFileSystem
    {

        public event EventHandler TransferToRequested;
        public event EventHandler<EventArgs> FolderChanged;

        private bool _expanding = false;
        private  IFileSystem _fileSystem;

        public FoldersControl()
        {
            InitializeComponent();

          
            _foldersTree.MouseDown += delegate(object sender, MouseEventArgs e)
            {
                _foldersTree.SelectedNode = _foldersTree.GetNodeAt(e.Location);

                this.OnEnter(EventArgs.Empty);
            };

            _foldersTree.ImageList = UIManager.Instance.SmallImageList;
           
            /*
            FormsUtils.ConfigureForDragDrop(_foldersTree,delegate(Control control) {
                return true;
                
            },this.HandleDrop);
            */


            TreeViewEventHandler setImage = delegate(object sender, TreeViewEventArgs e)
            {
                int closedIndex = UIManager.Instance.GetSmallImageListIndex(e.Node.Tag as Path, false);
                int openIndex = UIManager.Instance.GetSmallImageListIndex(e.Node.Tag as Path, true);
                e.Node.ImageIndex = e.Node.IsExpanded ? openIndex : closedIndex;
                e.Node.SelectedImageIndex = e.Node.IsExpanded ? openIndex : closedIndex;
            };
            _foldersTree.AfterExpand += setImage;
            _foldersTree.AfterCollapse += setImage;

            _foldersTree.AfterSelect += delegate(object sender, TreeViewEventArgs e)
            {
                if (e.Node == null)
                {
                    return;
                }
                this.OnFolderChanged();
            };


            _foldersTree.BeforeExpand += new TreeViewCancelEventHandler(_foldersTree_BeforeExpand);

        }

        public IFileSystem FileSystem
        {
            get { return _fileSystem; }
        }

        public void Initialize(IFileSystem fileSystem)
        {
            _fileSystem = fileSystem;

            _foldersTree.Nodes.Clear();

            TreeNode root = new TreeNode();
            root.Text = _fileSystem.Caption;
            root.Tag = Path.Root;

            this.AddLoading(root);

            _foldersTree.Nodes.Add(root);
        }

        public Path SelectedFolder
        {
            get
            {
                Path rt = null;

                this.InDisplay(delegate
                {
                    if (_foldersTree.SelectedNode == null)
                    {
                        return;
                    }
                    rt = _foldersTree.SelectedNode.Tag as Path;

                });

                return rt;
            }
            set
            {
                this.SetSelectedFolder(value);
            }
        }
























        private void SetSelectedFolder(Path path)
        {
            TreeNode currentNode = _foldersTree.Nodes[0];

            _expanding = true;
            this.Expand(currentNode, path.Parts);
        }

        private void HandleDrop(Control sender, object[] dropValues)
        {
            if (_foldersTree == sender)
            {
                return;
            }

            if (dropValues.Length > 0)
            {
                this.OnTransferToRequested();
            }
        }

      


        private void Expand(TreeNode node, string[] parts)
        {
            Path folder = node.Tag as Path;
          
            this.InBackground(delegate
            {
                IEnumerable<IFolderItem> folders = _fileSystem.GetFolders(folder);
                if (this.IsDisposed)
                {
                    return;
                }
                this.InDisplay(delegate
                {
                    node.Nodes.Clear();

                    foreach (IFolderItem child in folders)
                    {
                        TreeNode childNode = new TreeNode();
                        childNode.Text = child.Path.Name;
                        childNode.Tag = child.Path;

                        this.AddLoading(childNode);

                        node.Nodes.Add(childNode);
                    }

                    if (parts == null)
                    {
                        _expanding = false;
                        node.Expand();
                    }
                    else
                    {
                        if (parts.Length == 0)
                        {
                            _foldersTree.SelectedNode = node;
                            _expanding = false;
                            if (folder.Level == 0)
                            {
                                node.Expand();
                            }
                        }
                        else
                        {
                            foreach (TreeNode child in node.Nodes)
                            {
                                if (child.Text == parts[0])
                                {
                                    this.Expand(child, Utils.Subarray(parts, 1));
                                    return;
                                }
                            }
                            _foldersTree.SelectedNode = node;
                            _expanding = false;
                        }
                    }
                });
            });
        }

        private void _foldersTree_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if (!_expanding)
            {
                Application.DoEvents();
                this.InBackground(delegate
                {
                    this.InDisplay(delegate
                    {
                        this.Expand(e.Node,null);
                    });

                });
            }
        }



        private void AddLoading(TreeNode parent)
        {
            TreeNode loading = new TreeNode();
            loading.Text = "(loading...)";
            parent.Nodes.Add(loading);
        }

        protected void OnFolderChanged()
        {
            if (this.FolderChanged != null)
            {
                this.FolderChanged(this,EventArgs.Empty);
            }
        }

        protected void OnTransferToRequested()
        {
            if (this.TransferToRequested != null)
            {
                this.TransferToRequested(this, EventArgs.Empty);
            }
        }

    }
}

